package edu.ncsu.csc.csc454.project.wheel.node;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

import edu.ncsu.csc.csc454.project.gui.DropShadowPanel;
import edu.ncsu.csc.csc454.project.resources.Constants;
import edu.ncsu.csc.csc454.project.utilities.ImageUtilities;

/**
 * @author Team AW
 * @version 0.1
 */
@SuppressWarnings("serial")
public class Node extends DropShadowPanel {

    // private boolean isAlive;
    // private boolean isPaused;

    private volatile int    state       = Animation.STOPPED;

    private volatile int    currentIcon = 0;

    private int             iconCount   = Constants.ICON_COUNT;

    private Animation       t;
    private IconInfo        iconInfo;
    private BufferedImage[] icons;

    public Node(IconInfo iconInfo) {
        super();
        this.iconInfo = iconInfo;

        icons = new BufferedImage[iconCount];
        BufferedImage original = iconInfo.getIcon();

        int width = Constants.MIN_ICON_WIDTH;
        int height = Constants.MIN_ICON_HEIGHT;

        for (int i = 0; i < iconCount; i++) {
            icons[i] = ImageUtilities.resize(original, width + 2 * i, height + 2 * i);
        }

        setBounds(0, 0, Constants.MAX_ICON_WIDTH + 10, Constants.MAX_ICON_HEIGHT + 10);
        setOpaque(false);
        setSubject(icons[0]);

        t = new Animation();
        t.start();
    }

    @Override
    public void paintComponent(Graphics gX) {
        setSubject(icons[currentIcon]);
        super.paintComponent(gX);
    }

    public IconInfo getIconInfo() {
        return iconInfo;
    }

    public void startAnimation() {
        state = Animation.CYCLING_UP;
        t.interrupt();
    }

    public void stopAnimation() {
        state = Animation.STOPPED;
        t.interrupt();
    }

    public void pauseAnimation() {
        state = Animation.PAUSED;
        t.interrupt();
    }

    public void resumeAnimation() {
        state = Animation.CYCLING_DOWN;
        t.interrupt();
    }

    public boolean isPaused() {
        return state == Animation.PAUSED;
    }

    private class Animation extends Thread {

        private int              runState     = STOPPED;

        private static final int PAUSED       = 1;
        private static final int CYCLING_UP   = 2;
        private static final int CYCLING_DOWN = 3;
        private static final int STOPPED      = 4;

        private static final int FIRST_ICON   = 2;
        private static final int LAST_ICON    = Constants.ICON_COUNT - 1;

        @Override
        public synchronized void run() {

            while (true) {
                try {

                    switch (runState) {
                        case STOPPED:
                            if (currentIcon == 0) {
                                wait();
                                throw new InterruptedException();
                            }
                            currentIcon--;
                            break;
                        case PAUSED:
                            currentIcon = LAST_ICON;
                            repaint();
                            wait();
                            throw new InterruptedException();
                        case CYCLING_UP:
                            if (currentIcon == LAST_ICON) {
                                currentIcon--;
                                runState = CYCLING_DOWN;
                            } else {
                                currentIcon++;
                            }
                            break;
                        case CYCLING_DOWN:
                            if (currentIcon == FIRST_ICON) {
                                currentIcon++;
                                runState = CYCLING_UP;
                            } else {
                                currentIcon--;
                            }
                    }

                    repaint();
                    sleep(100);

                } catch (InterruptedException e) {
                    runState = state;
                }
            }
        }
    }
}
